package com.esms.utils.week;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Quarter;
import tk.mybatis.mapper.util.StringUtil;

import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * @description  : [
 * 支付宝账单周报统计，是以一周7天为维度的，
 * 自然周定义：以每月第一个星期一作为这个月一周的开始。
 * Java LocalDate API：每月第1个周一为该月第一周的算法。
 * 获得日期的所在周的周一
 * 获得日期这个月的第一个周一
 * 根据两个周一判断是这个月的第几周。
 * 注意考虑两个点，
 * 一是传进来的日期如果刚好是周一的情况，
 * 二是传来的日期如果是上一周的最后一周，也就是当月第一个周一大于当前日期所在的周一的情况，
 * 使用的是递归来计算，每次传值进来来都会循环计算当月的第一个周一
 * ]
 * @author       : [张丽峰]
 * @version      : [v1.0]
 * @createTime   : [2022/4/30 23:18]   
 */

public class DateWeekUtil {

	private static SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");

	/**
	 * 传入日期判断属于哪一年哪一月第几周
	 *
	 * @apiNote 以每月的第一个周一所在的周作为每月第一周
	 * @param date 时间格式(yyyyMMdd) 20200701
	 * @return java.lang.String 返回字符串(2020-06-W5) 2020年6月第5周
	 * @author kiring
	 */
	public static String getWeekOfMonthByDay(int date){
		DateTimeFormatter dfDay = DateTimeFormatter.ofPattern("yyyyMMdd");
		LocalDate localDate = LocalDate.of(date / 10000, (date / 100) % 100, date % 100);
		// 获得当前日期的所在周的周一(previousOrSame:如果当前日期是周一，就返回当前日期)
		LocalDate localDateMondy = LocalDate.of(date / 10000, (date / 100) % 100, date % 100).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
		LocalDate firstMonday = null;
		// 获得这个月的第一个周一(这个月的第一周)
		for(int day=1; day<=7; day++){
			DayOfWeek dayOfWeek = LocalDate.of(date / 10000, (date / 100) % 100, day).getDayOfWeek();
			if(DayOfWeek.MONDAY == dayOfWeek){
				firstMonday = LocalDate.of(date / 10000, (date / 100) % 100, day);
				break;
			}
		}
		String outYear = null;
		String outMonth = null;
		String outWeek = null;
		// 根据两个周一判断是这个月的第几周
		if(firstMonday.isBefore(localDateMondy) || firstMonday.isEqual(localDateMondy)){
			//a. 如果当月第一个周一小于等于当前日期所在的周一
			outYear = localDateMondy.format(dfDay).substring(0,4);
			outMonth = localDateMondy.format(dfDay).substring(4,6);
			outWeek = String.valueOf((localDateMondy.toEpochDay() - firstMonday.toEpochDay())/7 + 1);
			return outYear + "-" + outMonth + "-" + "第" + outWeek+"周";
		} else {
			//b. 如果当月第一个周一比当前日期所在的周一还要大
			// 计算上一个月最后一天所在周
			LocalDate lastMonthDate = localDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
			Integer lastMonthDay = Integer.valueOf(lastMonthDate.format(dfDay));
			return getWeekOfMonthByDay(lastMonthDay);
		}
	}


	/**
	 * 传入日期判断属于哪一年哪一月第几周:对应表字段：w_create_quarter:202202  就是  2022年2季度
	 *
	 * @apiNote 以每月的第一个周一所在的周作为每月第一周
	 * @param date 时间格式(yyyyMMdd) 20200701
	 * @return java.lang.String 返回字符串(2020-06-W5) 2020年6月第5周
	 * @author kiring
	 */
	public static DateBean getWeekByDay(int date){

		DateTimeFormatter dfDay = DateTimeFormatter.ofPattern("yyyyMMdd");
		LocalDate localDate = LocalDate.of(date / 10000, (date / 100) % 100, date % 100);
		// 获得当前日期的所在周的周一(previousOrSame:如果当前日期是周一，就返回当前日期)
		LocalDate localDateMondy = LocalDate.of(date / 10000, (date / 100) % 100, date % 100).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
		LocalDate firstMonday = null;
		// 获得这个月的第一个周一(这个月的第一周)
		for(int day=1; day<=7; day++){
			DayOfWeek dayOfWeek = LocalDate.of(date / 10000, (date / 100) % 100, day).getDayOfWeek();
			if(DayOfWeek.MONDAY == dayOfWeek){
				firstMonday = LocalDate.of(date / 10000, (date / 100) % 100, day);
				break;
			}
		}
		String outYear = null;
		String outMonth = null;
		String outWeek = null;
		DateBean dataBean = new DateBean();
		// 根据两个周一判断是这个月的第几周
		if(firstMonday.isBefore(localDateMondy) || firstMonday.isEqual(localDateMondy)){
			//a. 如果当月第一个周一小于等于当前日期所在的周一
			outYear = localDateMondy.format(dfDay).substring(0,4);
			outMonth = localDateMondy.format(dfDay).substring(4,6);
			outWeek = String.valueOf((localDateMondy.toEpochDay() - firstMonday.toEpochDay())/7 + 1);
			if(StringUtil.isNotEmpty(outYear)){
				dataBean.setYear(outYear);
			}
			if(StringUtil.isNotEmpty(outMonth)){
				dataBean.setMonth(outMonth);
			}
			if(StringUtil.isNotEmpty(outWeek)){
				dataBean.setWeek(outWeek);
			}
			return dataBean;
		} else {
			//b. 如果当月第一个周一比当前日期所在的周一还要大
			// 计算上一个月最后一天所在周
			LocalDate lastMonthDate = localDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
			Integer lastMonthDay = Integer.valueOf(lastMonthDate.format(dfDay));
			return getWeekByDay(lastMonthDay);
		}
	}

	/**
	 * 传入日期判断属于哪一季度
	 */
	public static String getQuarterByDate(Date date){
		//当前日期归属年
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		String year = String.valueOf(calendar.get(Calendar.YEAR));
		//当前日期归属季度
		Quarter quarter = DateUtil.quarterEnum(date);
		String quarterStr = "0"+String.valueOf(quarter.getValue());

		return year+quarterStr;
	}

	/**
	 * 根据日期字符串判断当月:对应表字段：w_week_MonYear归属月份
	 *
	 * @param str
	 * @return
	 * @throws Exception
	 */
	public static String getMonthForNowDay(String str) throws Exception {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date = sdf.parse(str);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		String month = String.valueOf(calendar.get(Calendar.MONTH) + 1);
		return month;
	}

	/**根据当前日期直接返回本周开始日期和结束日期**/
	public static String getFirstLastWeek(Date date){
		SimpleDateFormat formatterWeek = new SimpleDateFormat("yyyy年MM月dd日");
		String FirstWeekDay = formatterWeek.format(com.esms.utils.DateUtil.getFirstDayOfWeek(date));//当前日期本周开始第一天
		String LastWeekDay = formatterWeek.format(com.esms.utils.DateUtil.getLastDayOfWeek(date));//当前日期本周结尾最后一天
		String firstLastWeek = FirstWeekDay + " - " +LastWeekDay;;
		return firstLastWeek;
	}

	/**
	 * 根据日期字符串判断上个月
	 *
	 * @param
	 * @return
	 * @throws Exception
	 */
	public static String getBefMonthForNowDay() throws Exception {
		Date currentTime = new Date();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date date = sdf.parse(formatter.format(currentTime));
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		String month = "0"+String.valueOf(calendar.get(Calendar.MONTH));
		return month;
	}

	/**
	 * 计算当前日期是一年中第几季度：返回值：年+季度：2022+01/02/03/04
	 * **/
	public static String GetQuarterByDate(String date) throws Exception{

		if(date == ""|| "".equals(date)){
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date datePar = sdf.parse(date);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datePar);

		String year = String.valueOf(calendar.get(Calendar.YEAR));
		int mouth = datePar.getMonth()+1;

		if(mouth>=1 && mouth<=3){
			return year + "01";//第一季度
		}else if(mouth>=4 && mouth<=6){
			return year + "02";//第二季度
		}else if(mouth>=7 && mouth<=9){
			return year + "03";//第三季度
		}else if(mouth>=10 && mouth<=12){
			return year + "04";//第四季度
		}else{
			return "000000";
		}
	}
	/**
	 * 计算当前日期上一个季度：返回值：年+季度：2022+01/02/03/04
	 * **/
	public static String GetBeforeQuarterByDate(String date) throws Exception{

		if(date == ""|| "".equals(date)){
			return "";
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date datePar = sdf.parse(date);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datePar);

		String year = String.valueOf(calendar.get(Calendar.YEAR));
		int mouth = datePar.getMonth()+1;

		if(mouth>=1 && mouth<=3){
			return year + "04";//第一季度
		}else if(mouth>=4 && mouth<=6){
			return year + "01";//第二季度
		}else if(mouth>=7 && mouth<=9){
			return year + "02";//第三季度
		}else if(mouth>=10 && mouth<=12){
			return year + "03";//第四季度
		}else{
			return "000000";
		}
	}

	//Test
	public static void main(String args[]){

		Date currentTime = new Date();
		System.out.println("季度==="+getQuarterByDate(currentTime));


		int date = Integer.valueOf(formatter.format(currentTime));
		System.out.println("20220430归属哪一年==="+getWeekByDay(date).getYear());
		System.out.println("20220430归属哪一月==="+getWeekByDay(date).getMonth());
		System.out.println("20220430归属哪一周==="+getWeekByDay(date).getWeek());


		System.out.println("本周起始时间==="+getFirstLastWeek(currentTime));

		System.out.println("===============================================");
		//System.out.println("20220401==="+getWeekByDay(20220401));
		//System.out.println("20220403==="+getWeekByDay(20220403));
		System.out.println("===============================================");
		System.out.println("20220301==="+getWeekOfMonthByDay(20220301));
		System.out.println("20220302==="+getWeekOfMonthByDay(20220302));
		System.out.println("20220307==="+getWeekOfMonthByDay(20220307));
		System.out.println("===============================================");
		System.out.println("20220411==="+getWeekOfMonthByDay(20220411));
		System.out.println("20220414==="+getWeekOfMonthByDay(20220414));
		System.out.println("20220417==="+getWeekOfMonthByDay(20220417));
		System.out.println("===============================================");
		System.out.println("20220418==="+getWeekOfMonthByDay(20220418));
		System.out.println("20220419==="+getWeekOfMonthByDay(20220419));
		System.out.println("20220424==="+getWeekOfMonthByDay(20220424));
		System.out.println("===============================================");
		System.out.println("20220425==="+getWeekOfMonthByDay(20220425));
		System.out.println("20220428==="+getWeekOfMonthByDay(20220428));
		System.out.println("20220430==="+getWeekOfMonthByDay(20220430));
		System.out.println("20220501==="+getWeekOfMonthByDay(20220501));
		System.out.println("===============================================");
		System.out.println("20220502==="+getWeekOfMonthByDay(20220502));
		System.out.println("20220508==="+getWeekOfMonthByDay(20220508));



	}

}

